'\" te
.\" Copyright (c) 2006, Sun Microsystems, Inc.  All Rights Reserved.
.\" Copyright 1989 AT&T
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
.TH BUFCALL 9F "Jan 16, 2006"
.SH NAME
bufcall \- call a function when a buffer becomes available
.SH SYNOPSIS
.LP
.nf
#include <sys/types.h>
#include <sys/stream.h>



\fBbufcall_id_t\fR \fBbufcall\fR(\fBsize_t\fR \fIsize\fR, \fBuint_t\fR \fIpri\fR, \fBvoid \fR\fI*func\fRvoid \fI*arg\fR,
    \fBvoid\fR \fI*arg\fR);
.fi

.SH INTERFACE LEVEL
.sp
.LP
Architecture independent level 1 (DDI/DKI).
.SH PARAMETERS
.sp
.ne 2
.na
\fB\fIsize\fR\fR
.ad
.RS 8n
Number of bytes required for the buffer.
.RE

.sp
.ne 2
.na
\fB\fIpri\fR\fR
.ad
.RS 8n
Priority of the \fBallocb\fR(9F) allocation request (not used).
.RE

.sp
.ne 2
.na
\fB\fIfunc\fR\fR
.ad
.RS 8n
Function or driver routine to be called when a buffer becomes available.
.RE

.sp
.ne 2
.na
\fB\fIarg\fR\fR
.ad
.RS 8n
Argument to the function to be called when a buffer becomes available.
.RE

.SH DESCRIPTION
.sp
.LP
The \fBbufcall()\fR function serves as a \fBtimeout\fR(9F) call of
indeterminate length. When a buffer allocation request fails, \fBbufcall()\fR
can be used to schedule the routine \fIfunc\fR, to be called with the argument
\fIarg\fR when a buffer becomes available. \fIfunc\fR may call \fBallocb()\fR
or it may do something else.
.SH RETURN VALUES
.sp
.LP
If successful, \fBbufcall()\fR returns a \fBbufcall\fR \fBID\fR that can be
used in a call to \fBunbufcall()\fR to cancel the request. If the
\fBbufcall()\fR scheduling fails, \fIfunc\fR is never called and \fB0\fR is
returned.
.SH CONTEXT
.sp
.LP
The \fBbufcall()\fR function can be called from user, interrupt, or kernel
context.
.SH EXAMPLES
.LP
\fBExample 1 \fRCalling a function when a buffer becomes available:
.sp
.LP
The purpose of this \fBsrv\fR(9E) service routine is to add a header to all
\fBM_DATA\fR messages. Service routines must process all messages on their
queues before returning, or arrange to be rescheduled

.sp
.LP
While there are messages to be processed (line 13), check to see if it is a
high priority message or a normal priority message that can be sent on (line
14). Normal priority message that cannot be sent are put back on the message
queue (line 34). If the message was a high priority one, or if it was normal
priority and \fBcanputnext\fR(9F) succeeded, then send all but \fBM_DATA\fR
messages to the next module with \fBputnext\fR(9F) (line 16).

.sp
.LP
For \fBM_DATA\fR messages, try to allocate a buffer large enough to hold the
header (line 18). If no such buffer is available, the service routine must be
rescheduled for a time when a buffer is available. The original message is put
back on the queue (line 20) and \fBbufcall\fR (line 21) is used to attempt the
rescheduling. It will succeed if the rescheduling succeeds, indicating that
qenable will be called subsequently with the argument \fIq\fR once a buffer of
the specified size (\fBsizeof (struct hdr)\fR) becomes available. If it does,
\fBqenable\fR(9F) will put \fIq\fR on the list of queues to have their service
routines called. If \fBbufcall()\fR fails, \fBtimeout\fR(9F) (line 22) is used
to try again in about a half second.

.sp
.LP
If the buffer allocation was successful, initialize the header (lines 25-28),
make the message type \fBM_PROTO\fR (line 29), link the \fBM_DATA\fR message to
it (line 30), and pass it on (line 31).

.sp
.LP
Note that this example ignores the bookkeeping needed to handle \fBbufcall()\fR
and \fBtimeout\fR(9F) cancellation for ones that are still outstanding at close
time.

.sp
.in +2
.nf
 \fB1  struct hdr {
 2     unsigned int h_size;
 3     int          h_version;
 4  };
 5
 6  void xxxsrv(q)
 7     queue_t *q;
 8  {
 9     mblk_t *bp;
10     mblk_t *mp;
11     struct hdr *hp;
12
13     while ((mp = getq(q)) != NULL) {	/* get next message */
14         if (mp->b_datap->db_type >= QPCTL ||	/* if high priority */
                 canputnext(q)) {	/* normal & can be passed */
15            if (mp->b_datap->db_type != M_DATA)
16                 putnext(q, mp);	/* send all but M_DATA */
17            else {
18                bp = allocb(sizeof(struct hdr), BPRI_LO);
19                if (bp == NULL) {	/* if unsuccessful */
20                     putbq(q, mp);	/* put it back */
21                     if (!bufcall(sizeof(struct hdr), BPRI_LO,
                           qenable, q))	/* try to reschedule */
22                         timeout(qenable, q, drv_usectohz(500000));
23                        return (0);
24                 }
25                 hp = (struct hdr *)bp->b_wptr;
26                 hp->h_size = msgdsize(mp);	/* initialize header */
27                 hp->h_version = 1;
28                 bp->b_wptr += sizeof(struct hdr);
29                 bp->b_datap->db_type = M_PROTO;/* make M_PROTO  */
30                 bp->b_cont = mp;	/* link it */
31                 putnext(q, bp);	/* pass it on */
32            }
33         } else {	/* normal priority, canputnext failed */
34           putbq(q, mp);	/* put back on the message queue */
35           return (0);
36         }
37        }
	return (0);
38  }\fR
.fi
.in -2

.SH SEE ALSO
.sp
.LP
.BR srv (9E),
.BR allocb (9F),
.BR canputnext (9F),
.BR esballoc (9F),
.BR esbbcall (9F),
.BR putnext (9F),
.BR qenable (9F),
.BR testb (9F),
.BR timeout (9F),
.BR unbufcall (9F)
.sp
.LP
\fIWriting Device Drivers\fR
.sp
.LP
\fISTREAMS Programming Guide\fR
.SH WARNINGS
.sp
.LP
Even when \fIfunc\fR is called by \fBbufcall()\fR, \fBallocb\fR(9F) can fail if
another module or driver had allocated the memory before \fIfunc\fR was able to
call \fBallocb\fR(9F).
